#include "RealICompare.h"

RealICompare CompareObj;
ITypeInfo *CompareTypeInfo;

HRESULT LoadCompareTypeInfo()
{
    HRESULT hr;
    ITypeLib *pTypeLib = NULL;
    hr = LoadRegTypeLib(TLBID_IExampleEvts, 1, 0, 0, &pTypeLib);
    if (FAILED(hr)) return hr;
    hr = pTypeLib->GetTypeInfoOfGuid(DIID_ICompare, &CompareTypeInfo);
    pTypeLib->Release();
    if (FAILED(hr)) return hr;
    CompareTypeInfo->AddRef();
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealICompare::QueryInterface(REFIID riid, void **ppv)
{
    if (IsEqualIID(riid, IID_IUnknown) ||
        IsEqualIID(riid, DIID_ICompare))
    {
        *ppv = this;
        return S_OK;
    }

    *ppv = NULL;
    return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE RealICompare::AddRef()
{
    return 1;
}

ULONG STDMETHODCALLTYPE RealICompare::Release()
{
    return 1;
}

HRESULT STDMETHODCALLTYPE RealICompare::GetTypeInfoCount(UINT *pctinfo)
{
    *pctinfo = 0;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealICompare::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
    *ppTInfo = NULL;
    return S_OK;
}

HRESULT STDMETHODCALLTYPE RealICompare::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
    return E_NOTIMPL;
}

HRESULT STDMETHODCALLTYPE RealICompare::Invoke(DISPID dispIdMember, REFIID riid,
                                               LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
                                               VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
    if (CompareTypeInfo == NULL)
    {
        HRESULT hr = LoadCompareTypeInfo();
        if (FAILED(hr)) return hr;
    }
    return DispInvoke(this, CompareTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
}

LONG STDMETHODCALLTYPE RealICompare::Compare(const LPVOID elem1, const LPVOID elem2)
{
    if (*((DWORD *)elem1) == *((DWORD *)elem2)) return 0;
    if (*((DWORD *)elem1) < *((DWORD *)elem2)) return -1;
    return 1;
}
